from django.contrib.auth import login, authenticate, logout
from apps.users.utils import check_verify_email_token, generate_verify_email_url
from django.http import JsonResponse, HttpResponse, request
import json
from django import http
import re
from django_redis import get_redis_connection
from apps.users.models import User
# Create your views here.
from django.views import View
from django.contrib.auth.mixins import LoginRequiredMixin
from celery_tasks.email.tasks import send_email_active
from utils.views import LoginRequiredJSONMixin


class UsernameCountView(View):

    def get(self, request, username):
        # - 1 接收 用户名
        print(username)
        try:
            count = User.objects.filter(username=username).count()
        #   - 2 根据用户名查询数据库，查询数量有几个
        except Exception as e:
            print(e)
            return JsonResponse({"code": "0", "errmsg": "数据异常"})
        print("count=", count)
        #   - 3 返回json数据
        response = JsonResponse({"count": count, "code": "0", "errmsg": "OK"})
        return response


class MobileCountView(View):
    """判断手机号是否重复注册"""

    def get(self, request, mobile):
        """
        :param request: 请求对象
        :param mobile: 手机号
        :return: JSON
        """
        try:
            count = User.objects.filter(mobile=mobile).count()
        except Exception as e:
            return JsonResponse({"code": "0", "errmsg": "手机号以注册"})
        return JsonResponse({'code': 0, 'errmsg': 'OK', 'count': 0})


# 注册登录
class RegiserView(View):
    def post(self, request):
        # - 2.1 接收数据 获取到json数据
        body_byte = request.body
        # 把byte类型的json数据 转为字典
        data_dict = json.loads(body_byte)
        username = data_dict.get('username')
        password = data_dict.get('password')
        password2 = data_dict.get('password2')
        mobile = data_dict.get('mobile')
        sms_code = data_dict.get('sms_code')
        allow = data_dict.get('allow')
        print(allow)
        # - 2.2 验证数据 （数据不能为空 数据正则的验证）
        # all 里面传的列表的数据里 只要有一个是False 结果就是False
        if not all([username, password, password2, mobile, sms_code, allow]):
            return JsonResponse({'code': 400, 'errmsg': '数据上传错误'})
        # 判断用户名是否是5-20个字符
        if not re.match(r'^[a-zA-Z0-9_]{5,20}$', username):
            return http.JsonResponse({'code': 400, 'errmsg': 'username格式有误!'})
        # 判断密码是否是8-20个数字
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.JsonResponse({'code': 400, 'errmsg': 'password格式有误!'})
        # 判断两次密码是否一致
        if password != password2:
            return http.JsonResponse({'code': 400, 'errmsg': '两次输入不对!'})
        # 判断手机号是否合法
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.JsonResponse({'code': 400, 'errmsg': 'mobile格式有误!'})
        # 判断是否勾选用户协议
        if allow != True:
            return http.JsonResponse({'code': 400, 'errmsg': 'allow格式有误!'})
        try:
            user = User.objects.create_user(username=username, password=password, mobile=mobile)
        except Exception as e:
            print(e)
            return JsonResponse({'code': 400, 'errmsg': '注册失败'})
        redis = get_redis_connection('code')
        sms_code_redis = redis.get('smscode_%s' % mobile)

        # - 2  如果没取到 说明 过期了 ，返回错误
        if not sms_code_redis:
            return JsonResponse({'code': 400, 'errmsg': '驗證碼過期'})

        # - 3 和用户发来的对比
        sms_code_redis = sms_code_redis.decode()
        if sms_code != sms_code_redis:
            return JsonResponse({'code': 400, 'errmsg': '驗證碼输入错误'})
        login(request, user)
        print('登录')
        response = JsonResponse({"code": "0", "errmsg": "OK"})
        response.set_cookie('username', user.username, max_age=3600 * 24 * 15)
        return response


# 用户登录
class LoginView(View):
    def post(self, request):
        # 1 接收json数据
        body = request.body
        data_dict = json.loads(body)
        username = data_dict.get('username')
        password = data_dict.get('password')
        remembered = data_dict.get('remembered')

        # 2 验证数据是否为空  正则
        if not all([username, password, remembered]):
            return JsonResponse({'code': 400, 'errmsg': '写错了'})
        # 3 验证码用户名和密码是否正确
        if re.match('^1[3-9]\d{9}$', username):
            # 手机号
            User.USERNAME_FIELD = 'mobile'
        else:
            # account 是用户名
            # 根据用户名从数据库获取 user 对象返回.
            User.USERNAME_FIELD = 'username'

        user = authenticate(username=username, password=password)
        if not user:
            return JsonResponse({'code': 400, 'errmsg': '用户名密码错误'})

        # 4 状态保持
        login(request, user)

        # 5 判断是否记住登录
        if remembered:
            # 如果记住:  设置为两周有效
            request.session.set_expiry(None)
        else:
            # 如果没有记住: 关闭立刻失效
            request.session.set_expiry(0)
        # 6 返回响应
        response = JsonResponse({'code': 0, 'errmsg': 'ok'})
        response.set_cookie('username', user.username, max_age=3600 * 24 * 15)
        print('登录')
        return response


# 退出登录
class LogoutView(View):

    def delete(self, request):
        """实现退出登录逻辑"""
        # 清理session

        logout(request)
    # 退出登录，重定向到登录页
        response = JsonResponse({'code': 0,
                             'errmsg': 'ok'})
    # 退出登录时清除cookie中的username
        response.delete_cookie('username')

        return response
class UserInfoView(LoginRequiredMixin, View):
    """用户中心"""

    def get(self, request):
        """提供个人信息界面"""
        return http.JsonResponse({
            'code': 0,
            'errmsg': '个人中心',
             "info_data":{
                    "username":request.user.username,
                    "mobile": request.user.mobile,
                    "email": request.user.email,
                    "email_active": request.user.email_active
                }
            })

# 添加邮箱的视图
class SaveEmailView(LoginRequiredJSONMixin, View):
    def put(self, request):
        #  1 获取json数据 转为字典
        body = request.body
        data_dict = json.loads(body)

        #  2 从字典里拿到邮箱地址
        email = data_dict.get('email')
        #  3 校验
        if not email:
            return JsonResponse({'code': 300, 'errmsg': '邮箱不存在'})
        #  4 保存到数据库
        try:
            request.user.email = email
            request.user.save()
        except Exception as e:
            print(e)
            return JsonResponse({'code': 400, 'errmsg': '邮箱保存失败'})

        # 异步发送认证邮件

        # 获取要完整的邮箱验证的地址
        verify_url = generate_verify_email_url(request.user)
        message = '<p>尊敬的用户您好！</p>' \
                  '<p>感谢您使用美多商城。</p>' \
                  '<p>您的邮箱为：%s 。请点击此链接激活您的邮箱：</p>' \
                  '<p><a href="%s">点我激活</a></p>' % (email, verify_url)
        send_email_active.delay(email, message)

        #  5 返回相应
        return JsonResponse({'code': 0, 'errmsg': 'ok'})


class EmailVerifyView(View):
    def put(self, request):
        # - 1 接收请求（PUT）数据
        # - 2 获取token
        token = request.GET.get('token')

        # - 3 对token解密 获取解密数据里的user_id
        user_id = check_verify_email_token(token)
        # - 5 如果获取不到  说明过期
        if not user_id:
            return JsonResponse({'code': 400, 'errmsg': '激活邮件已经过期'})

        # - 6 根据user_id去数据库查询
        try:
            user = User.objects.get(id=user_id)
        except Exception as e:
            print(e)
            return JsonResponse({'code': 405, 'errmsg': '当前用户不存在'})

        # - 7 把查到user对象的 email_active字段 改为true  不要忘记save
        user.email_active = True
        user.save()
        return JsonResponse({'code': 0, 'errmsg': '激活成功'})
#修改密码
class ChangePasswordView(LoginRequiredMixin, View):
    """修改密码"""

    def put(self, request):
        """实现修改密码逻辑"""
        # 接收参数
        dict = json.loads(request.body.decode())
        old_password = dict.get('old_password')
        new_password = dict.get('new_password')
        new_password2 = dict.get('new_password2')

        # 校验参数
        if not all([old_password, new_password, new_password2]):
           return JsonResponse({'code':400,'errmsg':'缺少必传参数'})


        result = request.user.check_password(old_password)
        if not result:
            return JsonResponse({'code':400,'errmsg':'原始密码不正确'})

        if not re.match(r'^[0-9A-Za-z]{8,20}$', new_password):
            return JsonResponse({'code':400,'errmsg':'密码最少8位,最长20位'})

        if new_password != new_password2:
            return JsonResponse({'code':400, 'errmsg':'两次输入密码不一致'})

        # 修改密码
        try:
            request.user.set_password(new_password)
            request.user.save()
        except Exception as e:

            return JsonResponse({'code':400,'errmsg':'修改密码失败'})

        # 清理状态保持信息
        logout(request)

        response = JsonResponse({'code':0,'errmsg':'ok'})

        response.delete_cookie('username')

        # # 响应密码修改结果：重定向到登录界面
        return response
